using System;
using System.Data;
using System.Drawing;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Text.RegularExpressions;

using Danser_AJAXEnabledWebApplication.Query_Popups;
using Danser_AJAXEnabledWebApplication.User_Controls;
using Danser_AJAXEnabledWebApplication.PageExt;
using Danser_Control.Managers;
using Danser_Entity.Entities;
using Danser_Entity.Queries.Data;
using Danser_Entity.Queries.Filters;

namespace Danser_AJAXEnabledWebApplication
{
    /// <summary>
    /// Page to accept or reject tests according to their results
    /// </summary>
    public partial class EditData : TestDataDisplay
    {
        #region Constants:

        //extended Tests data object data source parameters
        private const String CONFIRMED_BUTTON_ID = "confirmedLinkButton";
        private const String ANCHOR_BUTTON_ID = "anchorLinkButton";

        #endregion

        #region Page Load:

        /// <summary>
        /// loads the page...
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected override void Page_Load(object sender, EventArgs e)
        {
            base.Page_Load(sender, e);

            if (!IsPostBack) //first time
            {
                //set columns in test info multi select according to the template
                DisplayColumnsTemplate(dataGridView, columnsMultiSelectList, 1, COLUMNS_TEMPLATE);

                //feed columns to results multi select list
                DisplayColumnsTemplate(testDataGridView, testResultColumnsMultiSelectList, 0, null);

                //reset columns selection
                SetHeaderColumnSpan(testResultColumnsMultiSelectList);
            }
            
            //decide what tests to display
            String initialFilterQuery =
                nonConfirmedCheckBox.Checked ?
                DBConstants.TEST_INFO_IS_CONFIRMED + " = 'false'" :
                null;

            testInfoObjectDataSource.SelectParameters[ODS_FILTER_PARAMETER].DefaultValue = initialFilterQuery;
        }

        #endregion

        #region Filter Tables Columns Panes:

        /// <summary>
        /// event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void filterButton_Click(object sender, EventArgs e)
        {
            _pageFormatter.FilterColumnsByListSelection(dataGridView, columnsMultiSelectList);
        }

        /// <summary>
        /// event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void testResultfilterButton_Click(object sender, EventArgs e)
        {
            _pageFormatter.FilterColumnsByListSelection(testDataGridView, testResultColumnsMultiSelectList);

            SetHeaderColumnSpan(testResultColumnsMultiSelectList);
        }

        #endregion

        #region Filter Tables Rows:

        //Test Info Table
        /// <summary>
        /// event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void filterTestInfoButton_Click(object sender, EventArgs e)
        {
            _pageFormatter.ToggleButtonText((Button)sender, new String[] { "Search Tests", "Hide Search" });

            HandleFilterRowsPanel(testInfoQueryPanel, testInfoQueryExpressionBuilder, TEST_INFO_SEARCH);
        }

        /// <summary>
        /// event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void executeTestInfoQueryButton_Click(object sender, EventArgs e)
        {
            ExecuteSelect(testInfoObjectDataSource, testInfoQueryExpressionBuilder);
        }

        //Test Result Table
        /// <summary>
        /// event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void filterTestResultButton_Click(object sender, EventArgs e)
        {
            _pageFormatter.ToggleButtonText((Button)sender, new String[] {"Search Results", "Hide Search"});

            HandleFilterRowsPanel(testResultQueryPanel, testResultQueryExpressionBuilder, TEST_RESULTS_SEARCH);
        }

        /// <summary>
        /// event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void executeTestResultQueryButton_Click(object sender, EventArgs e)
        {
            ExecuteSelect(testResultsObjectDataSource, testResultQueryExpressionBuilder);
        }

        #endregion

        #region Inner Row Control Handlers:

        /// <summary>
        /// event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void anchorLinkButton_Click(object sender, EventArgs e)
        {
            LinkButton button = sender as LinkButton;
            SwitchBooleanFieldValue(DBConstants.TEST_INFO_IS_ANCHOR, button);

            RefreshTests();
        }

        /// <summary>
        /// event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void confirmedLinkButton_Click(object sender, EventArgs e)
        {
            LinkButton button = sender as LinkButton;
            SwitchBooleanFieldValue(DBConstants.TEST_INFO_IS_CONFIRMED, button);

            RefreshTests();
        }

        /// <summary>
        /// event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void displayRowLinkButton_Click(object sender, EventArgs e)
        {
            //get the containing row for testinfo index
            LinkButton button = sender as LinkButton;
            GridViewRow row = (button.Parent.Parent) as GridViewRow;
            
            String testInfoIndex = (String)dataGridView.DataKeys[row.RowIndex].Value;

            displyResultsByTestID(testInfoIndex);

        }

        #endregion

        #region DataGrid Handlers:

        /// <summary>
        /// Called for each data row to be bound to the datagrid
        /// </summary>
        /// <param name="sender">The data grid</param>
        /// <param name="e">contains the relevant row to bind data to</param>
        protected void dataGridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            GridViewRow row = e.Row;
            if (row.RowType == DataControlRowType.DataRow)
            {
                //handle confirmed field
                FormatBooleanField(row, CONFIRMED_BUTTON_ID);

                //handle anchor field
                FormatBooleanField(row, ANCHOR_BUTTON_ID);

                String testIdx = (String)dataGridView.DataKeys[row.RowIndex].Value;

                try
                {
                    IList<ValidationTemplate> failedValidations = _validationManager.GetFailingTemplatesForTest(testIdx);

                    //handle validation status field
                    Label validationStatus = row.FindControl(VALIDATION_STATUS_LABEL_ID) as Label;
                    validationStatus.Text = failedValidations.Count == 0 ? "Passed" : "Failed";
                    validationStatus.ForeColor = failedValidations.Count == 0 ? Color.Green : Color.Red;

                    //handle failed validation field
                    TextBox failedValidationsTextBox = row.FindControl(VALIDATIONS_TEXT_BOX_ID) as TextBox;

                    failedValidationsTextBox.BackColor =
                        row.RowIndex % 2 == 0 ?
                        dataGridView.RowStyle.BackColor :
                        dataGridView.AlternatingRowStyle.BackColor;
                    
                    _pageFormatter.FormatFailedValidations(failedValidationsTextBox, failedValidations);
                }
                catch (Exception exception)
                {
                    HandleGenericErrorPage(exception);
                }
            }
        }

        #endregion

        #region Helpers:

        /// <summary>
        /// Display only columns selected in the template pattern.
        /// <para>This method uses regular expressions</para>
        /// </summary>
        /// <param name="grid">The grid with columns to display in list</param>
        /// <param name="list">The list</param>
        /// <param name="startIndex"></param>
        /// <param name="template">The string pattern consisting of columns to display. Must be in regular expression pattern format</param>

        private void DisplayColumnsTemplate(GridView grid, MultiSelectList list, int startIndex, String template)
        {
            Regex pattern = 
                template != null ? 
                new Regex(template) : 
                new Regex("()*");       //allways true

            //feed columns list
            for (int i = startIndex; i < grid.Columns.Count; i++)
            {
                String headerText = grid.Columns[i].HeaderText;
                ListItem item = new ListItem(headerText);

                //show only the pattern columns
                item.Selected = pattern.IsMatch(headerText);
                grid.Columns[i].Visible = item.Selected;

                list.Items.Add(item);
            }
        }

        /// <summary>
        /// Format display of a boolean field in a datagrid row
        /// </summary>
        /// <param name="row">The GridView row containing the field</param>
        /// <param name="fieldKey">The server control id</param>
        private void FormatBooleanField(GridViewRow row, String fieldKey)
        {
            LinkButton button = (LinkButton)row.FindControl(fieldKey);
            if (button != null)
            {               
                button.Text =
                    button.Text.ToLower().Equals("false") ? "No" : "Yes";
                button.ForeColor =
                    button.Text.Equals("No") ? Color.Red : Color.Green;
                button.ToolTip = "Click to modify";
            }
        }

        /// <summary>
        /// Toggle a boolean typed field's value
        /// </summary>
        /// <param name="fieldName">the field name</param>
        /// <param name="button">the button triggering the value change</param>
        private void SwitchBooleanFieldValue(String fieldName, LinkButton button)
        {
            //get the containing row
            GridViewRow row = (button.Parent.Parent) as GridViewRow;

            bool value = button.Text.Equals("Yes");
            String id = (String)dataGridView.DataKeys[row.RowIndex].Value;

            IDataManager dataManager = ManagerFactory.DataManager();
            try
            {
                dataManager.UpdateState(id, fieldName, !value);
                //refresh datagrid
                dataGridView.DataBind();
            }
            catch (Exception exception)
            {
                HandleGenericErrorPage(exception);
            }
        }

        /// <summary>
        /// Display the results according to selected test
        /// </summary>
        /// <param name="testInfoIndex">the id of the selected test</param>
        private void displyResultsByTestID(String testInfoIndex)
        {
            //save testInfoIndex in session for further use
            Session[SELECTED_TEST_ID] = testInfoIndex;

            numericResultsDataPanel.Visible =
                testInfoIndex != null && toggleDisplayModeButton.Text.Equals(RESULTS_DISPLAY_MODE[0]);

            graphResultsDataPanel.Visible = testInfoIndex != null && !numericResultsDataPanel.Visible;

            //update graph control with test id
            try
            {
                _pageFormatter.SetGraphInput(EditDataGraphUserControl, testInfoIndex);
            }
            catch (Danser_Control.Exceptions.DanserGraphException graphException)
            {
                HandleGenericErrorPage(graphException);
            }

            if (!String.IsNullOrEmpty(testInfoIndex))
            {
                Condition condition =
                    new Condition(
                        Groups.Information,
                        TestInfoFields.TestInfoIndex.ToString(),
                        ComparingOperators.EQUALS,
                        testInfoIndex.ToString(),
                        BooleanOperators.AND,
                        false);

                testResultQueryExpressionBuilder.SetInitialCondition(condition);
            }

            //build initial rule
            GetTestResults(testInfoIndex, testResultsObjectDataSource, testDataGridView);
        }

        /// <summary>
        /// refresh the test displayed in test info grid
        /// </summary>
        private void RefreshTests()
        {
            ExecuteSelect(testInfoObjectDataSource, testInfoQueryExpressionBuilder, false);
            //reset results grid display
            displyResultsByTestID(null);
        }

        #endregion

        #region TestData Grid:

        /// <summary>
        /// event handler - toggle the results display modes for a selected test
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void toggleDisplayModeButton_Click(object sender, EventArgs e)
        {
            ToggleView(numericResultsDataPanel, graphResultsDataPanel, toggleDisplayModeButton, EditDataGraphUserControl);          
        }

        protected void nonConfirmedCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            Condition testInfoInitial =
                nonConfirmedCheckBox.Checked ?
                new Condition(
                    Groups.Information,
                    TestInfoFields.isConfirmed.ToString(),
                    ComparingOperators.EQUALS,
                    "false",
                    BooleanOperators.AND,
                    false) :
                new TrueCondition();

            testInfoQueryExpressionBuilder.SetInitialCondition(testInfoInitial);
            
            //refresh display
            RefreshTests();

        }

        /// <summary>
        /// handle creation event by adding the header row aggregating test results columns
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void testDataGridView_RowCreated(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.Header)
            {
                FormatResultsHeader(testDataGridView);
            }
        }

        /// <summary>
        /// invoked when user wants to clear anchors display
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void removeAnchorButton_Click(object sender, EventArgs e)
        {
            Session[SelectAnchors.SESSION_SELECTED_ANCHORS] = new List<String>();
            RefreshAnchorsInGraph(EditDataGraphUserControl);

            removeAnchorButton.Enabled = false;
        }

        #endregion

        #region Popups:

        /// <summary>
        /// event handler - refresh update panel to insert selected anchor tests details to he graph builder
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void selectAnchorRefreshButton_Click(object sender, EventArgs e)
        {
            removeAnchorButton.Enabled = true;
            RefreshAnchorsInGraph(EditDataGraphUserControl);
        }

        #endregion

        #region AbstractPage Implementation:

        /// <see cref="Danser_AJAXEnabledWebApplication.AbstractPage.InnerValidatePermission"/>
        protected override bool InnerValidatePermission(PermissionLevel permissionlevel)
        {
            return permissionlevel == PermissionLevel.Admin || permissionlevel == PermissionLevel.Manager;
        }

        #endregion

    }
}
